﻿using System.Net;
using AlibabaCloud.OpenApiClient.Models;
using AlibabaCloud.SDK.Dysmsapi20170525;
using AlibabaCloud.SDK.Dysmsapi20170525.Models;
using Devonline.AspNetCore;
using Devonline.Core;
using Microsoft.Extensions.Logging;

namespace Devonline.CloudService.Aliyun;

/// <summary>
/// 阿里云接口短信发送服务
/// </summary>
public class SmsService : ISmsService
{
    private readonly Client _client;
    protected readonly ILogger<SmsService> _logger;
    public SmsService(ILogger<SmsService> logger, ISmsEndpoint endpoint)
    {
        ArgumentNullException.ThrowIfNull(endpoint.Host);
        ArgumentNullException.ThrowIfNull(endpoint.AppId);
        ArgumentNullException.ThrowIfNull(endpoint.Secret);
        _logger = logger;
        _client = new Client(new Config { Endpoint = endpoint.Host, AccessKeyId = endpoint.AppId, AccessKeySecret = endpoint.Secret });
    }

    /// <summary>
    /// 阿里云接口发送短信
    /// </summary>
    /// <param name="model">短信内容数据模型</param>
    /// <returns></returns>
    public async Task SendAsync(ISmsModel model)
    {
        var request = GetSmsRequest(model.SignName, model.TemplateCode, model.TemplateParam, [.. model.PhoneNumbers]);
        _logger.LogInformation("The sms service will send sms message to: " + request.PhoneNumbers);
        var response = await _client.SendSmsAsync(request);
        switch (response.StatusCode)
        {
            case (int)HttpStatusCode.OK when response.Body.Code == HttpStatusCode.OK.ToString():
                _logger.LogInformation($"The sms service send sms message success with code: {response.Body.Code}, message: {response.Body.Message}, and sms content: {model.ToJsonString()}");
                break;
            default:
                throw new Exception($"The sms service send sms message failed with code: {response.Body.Code}, message: {response.Body.Message}");
        }
    }
    /// <summary>
    /// 发送短信息
    /// </summary>
    /// <param name="templateParam">短信内容模板中的变量和值的集合</param>
    /// <param name="phoneNumbers">发送的手机号码</param>
    /// <returns></returns>
    public async Task SendAsync(string signName, string templateCode, Dictionary<string, string> templateParam, params string[] phoneNumbers)
    {
        var request = GetSmsRequest(signName, templateCode, templateParam, phoneNumbers);
        _logger.LogInformation("The sms service will send sms message to: " + request.PhoneNumbers);
        var response = await _client.SendSmsAsync(request);
        switch (response.StatusCode)
        {
            case (int)HttpStatusCode.OK when response.Body.Code == HttpStatusCode.OK.ToString():
                _logger.LogInformation($"The sms service send sms message success with code: {response.Body.Code}, message: {response.Body.Message}, and sms content: {request.ToJsonString()}");
                break;
            default:
                throw new Exception($"The sms service send sms message failed with code: {response.Body.Code}, message: {response.Body.Message}");
        }
    }

    /// <summary>
    /// 发送短信息
    /// </summary>
    /// <param name="signName">短信签名</param>
    /// <param name="templateCode">短信内容模板编号</param>
    /// <param name="templateParam">短信内容模板中的变量和值的集合</param>
    /// <param name="phoneNumbers">发送的手机号码</param>
    /// <returns></returns>
    private SendSmsRequest GetSmsRequest(string signName, string templateCode, Dictionary<string, string> templateParam, params string[] phoneNumbers)
    {
        if (!templateParam.Any())
        {
            throw new Exception("the sms service send message need template params!");
        }

        if (phoneNumbers.Length == 0)
        {
            throw new Exception("the sms service send message need phone number(s)!");
        }

        return new SendSmsRequest
        {
            SignName = signName,
            TemplateCode = templateCode,
            PhoneNumbers = phoneNumbers.ToString<string>(),
            TemplateParam = templateParam.ToJsonString(),
        };
    }
}

/// <summary>
/// 发送短信验证码的服务
/// </summary>
public class SmsCaptchaService : SmsService, ISmsService, ISmsCaptchaService
{
    private readonly ISmsModel _smsModel;
    public SmsCaptchaService(ILogger<SmsService> logger, ISmsEndpoint endpoint, ISmsModel smsModel) : base(logger, endpoint) => _smsModel = smsModel;

    /// <summary>
    /// 发送手机验证码, 短信验证码的模板变量名字固定为 : code
    /// </summary>
    /// <param name="phoneNumbers">发送的手机号码</param>
    /// <returns></returns>
    public async Task<string> SendCaptchaAsync(params string[] phoneNumbers)
    {
        var phoneNumberStrings = phoneNumbers.ToString<string>();
        var code = new Random(DateTime.Now.Millisecond).Next(100000, 999999).ToString();
        _logger.LogDebug($"SMS service will send captcha: {code} to {phoneNumberStrings}");
        await SendAsync(_smsModel.SignName, _smsModel.TemplateCode, new Dictionary<string, string> { { nameof(code), code } }, phoneNumbers);
        _logger.LogInformation($"SMS service send captcha: {code} to {phoneNumberStrings} success");
        return code;
    }
}